<?php
namespace app\index\controller;

use think\Controller;
use think\Loader;
use think\Validate;

/**
 * 验证
 */
class Yz extends Controller
{
    ////////////////////////////////        验证器        ////////////////////////////////

    /**
     * 1. 独立验证
     */
    public function index()
    {
        $validate = new Validate([
            'name' => 'require|max:25', // 不能为空；长度不能超过25
            'email' => 'email',  // 格式不符
        ]);
        $data = [
            'name' => 'thinkphp',
            'email' => 'thinkphp@126.com',
        ];

        if(!$validate->check($data)){
            print_r($validate->getError());
        } else {
            return '验证器 → 独立验证';
        }

//        print_r($validate->check($data));   // 输出：1
//        dump($validate->check($data));   // 输出：true
    }

    /**
     * 2. 验证器
     */
    public function a()
    {
        $data = [
            'name' => 'thinkphp',
            'email' => 'thinkphp@126.com',
        ];
        $validate = Loader::validate('Yz'); // Loader ?? 干嘛的

        if(!$validate->check($data)){
            print_r($validate->getError());
        }
    }


    ////////////////////////////////       验证规则       ////////////////////////////////

    // 5.0.4	支持传入field参数批量设置验证字段的描述信息

    /**
     * 1. 设置规则
     */
    public function b()
    {
        // 可以在实例化Validate类的时候传入验证规则
        $rules = [
            'name'  => 'require|max:25',
            'age'   => 'number|between:1,120',
        ];
        $validate = new Validate($rules);

        // 也可以使用rule方法动态添加规则
        $rules = [
            'name'  => 'require|max:25',
            'age'   => 'number|between:1,120',
        ];
        $validate = new Validate($rules);
        $validate->rule('zip', '/^\d{6}$/');
        $validate->rule([
            'email'   => 'email',
        ]);
    }

    /**
     * 2. 规则定义
     */
    public function c()
    {
        // 对于一个字段可以设置多个验证规则，使用|分割
        $rules = [
            'name'  => 'require|max:25',
            'age'   => 'number|between:1,120',
        ];
        $validate = new Validate($rules);

        // 采用数组方式定义多个规则（适用于你的验证规则中有|的情况）
        $rules = [
            'name'  => ['require','max'=>25],
            'age'   => ['number','between'=>'1,120'],
        ];
        $validate = new Validate($rules);
    }

    /**
     * 3. 属性定义
     */
    public function d()
    {
        // 实际在定义验证类的时候，可以通过属性的方式直接定义验证规则等信息
    }

    /**
     * 4. 验证数据
     */
    public function e()
    {
        $rule = [
            'name'  => 'require|max:25',
            'age'   => 'number|between:1,120',
            'email' => 'email',
        ];

        $msg = [
            'name.require' => '名称必须',
            'name.max'     => '名称最多不能超过25个字符',
            'age.number'   => '年龄必须是数字',
            'age.between'  => '年龄只能在1-120之间',
            'email'        => '邮箱格式错误',
        ];

        $data = [
            'name'  => 'thinkphp',
            'age'   => 10,
            'email' => 'thinkphp@qq.com',
        ];

        $validate = new Validate($rule, $msg);
        $result = $validate->check($data);
        print_r($result);
        print_r($validate->getError());

        // 批量验证
        $validate = new Validate($rule, $msg);
        $result   = $validate->batch()->check($data);
        // ？？？？怎么输出
        print_r($result);
        print_r($validate);

        // 如果你定义了Yz验证器类的话，可以使用下面的验证代码：
        $data = [
            'name'  => 'thinkphp',
            'age'   => 10,
            'email' => 'thinkphp@qq.com',
        ];
        $validate = Loader::validate('Yz');
        if(!$validate->check($data)){
            dump($validate->getError());
        }
    }

    /**
     * 5. 闭包函数验证
     */
    public function f()
    {
        // 可以对某个字段使用闭包验证
        $validate = new Validate([
            // 第一个参数是当前字段的值，第二个参数是全部数据
            'name' => function($value,$data){
                return 'thinkphp'==$value?true:false;
            },
        ]);
        $data = [
            'name'  => 'thinkphp',  // 值：abc
        ];
        if(!$validate->check($data)){
            dump($validate->getError());
        } else {
            echo '闭包函数验证';
        }
    }

    /**
     * 6. 自定义验证规则
     */
    public function g()
    {
        // 系统内置了一些常用的规则，如果还不够用，可以自己扩展验证规则
        $data = [
            'name'  => 'abc', // thinkphp
            'email' => 'thinkphp@qq.com',
        ];
        $validate = Loader::validate('Yz');
        if(!$validate->check($data)){
            dump($validate->getError());
        } else {
            echo '自定义验证规则';
        }

        // 如果没有使用验证器类，则支持使用extend方法扩展验证规则
        // ?????????????????????
        $validate = new Validate(['name' => 'checkName:1']);
        $validate->extend('checkName', function ($value, $rule) {
            return $rule == $value ? true : '名称错误';
        });
        $data   = ['name' => 1];
        $result = $validate->check($data);

        // 支持批量注册验证规则
        // ?????????????????????????????
        $validate = new Validate(['name' => 'checkName:1']);
        $validate->extend([
            'checkName'=> function ($value, $rule) {
                return $rule == $value ? true : '名称错误';
            },
            'checkStatus'=> [$this,'checkStatus']
        ]);
        $data   = ['name' => 1];
        $result = $validate->check($data);
    }

    /**
     * 7. 设置字段信息
     */
    public function h()
    {
        // V5.0.4+版本开始，验证类的架构方法支持传入field参数批量设置字段的描述信息
        $rule = [
            'name'  => 'require|max:25',
            'age'   => 'number|between:1,120',
            'email' => 'email',
        ];

        $field = [
            'name'  => '名称',
            'age'   => '年龄',
            'email' => '邮箱',
        ];

        $data = [
            'name'  => 'thinkphp',
            'age'   => 10,
            'email' => 'thinkphp@qq.com',
        ];

        $validate = new Validate($rule, [] , $field);
        $result   = $validate->check($data);
        if(!$result){
            dump($validate->getError());
        } else {
            echo '设置字段信息';
        }
    }


    ////////////////////////////////       错误信息       ////////////////////////////////

    // 验证规则的错误提示信息有三种方式可以定义

    /**
     * 1. 使用默认的错误提示信息
     */
    public function i()
    {
        // 如果没有定义任何的验证提示信息，系统会显示默认的错误信息
        $rule = [
            'name'  => 'require|max:25',
            'age'   => 'number|between:1,120',
            'email' => 'email',
        ];

        $data = [
            'name'  => 'thinkphp',
            'age'   => 121,
            'email' => 'thinkphp@qq.com',
        ];
        $validate = new Validate($rule);
        $result   = $validate->check($data);
        if(!$result){
            echo $validate->getError();
        }

        // 可以给age字段设置中文名
        $rule = [
            'name'  => 'require|max:25',
            'age|年龄'   => 'number|between:1,120',
            'email' => 'email',
        ];

        $data = [
            'name'  => 'thinkphp',
            'age'   => 121,
            'email' => 'thinkphp@qq.com',
        ];
        $validate = new Validate($rule);
        $result   = $validate->check($data);
        if(!$result){
            echo $validate->getError();
        }
    }

    /**
     * 2. 验证规则和提示信息分开定义
     */
    public function j()
    {
        $rule = [
            'name'  => 'require|max:25',
            'age'   => 'number|between:1,120',
            'email' => 'email',
        ];
        $msg = [
            'name.require' => '名称必须',
            'name.max'     => '名称最多不能超过25个字符',
            'age.number'   => '年龄必须是数字',
            'age.between'  => '年龄必须在1~120之间',
            'email'        => '邮箱格式错误',
        ];
        $data = [
            'name'  => 'thinkphp',
            'age'   => 121,
            'email' => 'thinkphp@qq.com',
        ];
        $validate = new Validate($rule,$msg);
        $result   = $validate->check($data);
        if(!$result){
            echo $validate->getError();
        }
    }

    /**
     * 3. 验证规则和提示信息一起定义
     */
    public function k()
    {
        $rule = [
            ['name','require|max:25','名称必须|名称最多不能超过25个字符'],
            ['age','number|between:1,120','年龄必须是数字|年龄必须在1~120之间'],
            ['email','email','邮箱格式错误']
        ];

        $data = [
            'name'  => 'thinkphp',
            'age'   => 121,
            'email' => 'thinkphp@qq.com',
        ];
        $validate = new Validate($rule);
        $result   = $validate->check($data);
        if(!$result){
            echo $validate->getError();
        }
    }

    /**
     * 4. 使用多语言
     */
    // ?????????????????????
    public function l()
    {
        // 在定义验证信息的时候使用 {%语言变量} 替代 原来的验证错误信息
        $rule = [
            'name'  => 'require|max:25',
            'age'   => 'number|between:1,120',
            'email' => 'email',
        ];
        $msg = [
            'name.require' => '{%name_require}',
            'name.max'     => '{%name_max}',
            'age.number'   => '{%age_number}',
            'age.between'  => '{%age_between}',
            'email'        => '{%email_error}',
        ];
        $data = [
            'name'  => 'thinkphp',
            'age'   => 121,
            'email' => 'thinkphp@qq.com',
        ];
        $validate = new Validate($rule,$msg);
        $result   = $validate->check($data);
        if(!$result){
            echo $validate->getError();
        }
    }


    ////////////////////////////////       验证场景       ////////////////////////////////

    // 5.0.4	增加hasScene方法用于检查是否存在验证场景

    /**
     * 1. 验证场景
     */
    public function m()
    {
        $rule = [
            'name'  => 'require|max:25',
            'age'   => 'number|between:1,120',
            'email' => 'email',
        ];
        $msg = [
            'name.require' => '名称必须',
            'name.max'     => '名称最多不能超过25个字符',
            'age.number'   => '年龄必须是数字',
            'age.between'  => '年龄只能在1-120之间',
            'email'        => '邮箱格式错误',
        ];
        $data = [
            'name'  => 'thinkphp',
            'age'   => 1012,
            'email' => 'thinkphp@qq.com',
        ];
        $validate = new Validate($rule,$msg);
        // 表示验证edit场景（该场景定义只需要验证name和age字段）
        $validate->scene('edit', ['name', 'age']);
        $result = $validate->scene('edit')->check($data);
        if(!$result){
            echo $validate->getError();
        } else {
            echo '验证场景';
        }
    }

    // 如果使用了验证器，可以直接在类里面定义场景
    public function n()
    {
        $data = [
            'name'  => 'thinkphp',
            'age'   => 10,
            'email' => 'thinkphp@qq.com',
        ];

        $validate = new \app\index\validate\Yz();
        $result = $validate->scene('edit')->check($data);
    }

    // 可以在定义场景的时候对某些字段的规则重新设置
    public function o()
    {

    }

    // 可以对场景设置一个回调方法，用于动态设置要验证的字段
    public function p()
    {
        $rule = [
            'name'  => 'require|max:25',
            'age'   => 'number|between:1,120',
            'email' => 'email',
        ];
        $msg = [
            'name.require' => '名称必须',
            'name.max'     => '名称最多不能超过25个字符',
            'age.number'   => '年龄必须是数字',
            'age.between'  => '年龄只能在1-120之间',
            'email'        => '邮箱格式错误',
        ];
        $data = [
            'name'  => 'thinkphp',
            'age'   => 10,
            'email' => 'thinkphp@qq.com',
        ];
        $validate = new Validate($rule);
        $validate->scene('edit', function($key,$data){
            return 'email'==$key && isset($data['id'])? true : false;
        });
        $result = $validate->scene('edit')->check($data);
    }


    ///////////////////////////////      控制器验证      ////////////////////////////////

    // 控制器 继承了\think\Controller
    // 调用控制器类提供的validate方法进行验证
    public function q()
    {
        $result = $this->validate(
            [
                'name'  => 'thinkphp',
                'email' => 'thinkphp@qq.com',
            ],
            [
                'name'  => 'require|max:25',
                'email'   => 'email',
            ]);
        if(true !== $result){
            dump($result);
        }
    }

    // 定义了验证器类
    public function r()
    {
        $data = [
            'name'  => 'thinkphp',
            'email' => 'thinkphp@qq.com',
        ];
        $result = $this->validate($data,'Yz');
        if(true !== $result){
            dump($result);
        }

        // 如果要使用场景
        $result = $this->validate($data,'Yz.edit');
        if(true !== $result){
            dump($result);
        }

        // 在validate方法中还支持做一些前置的操作回调
        // ?????????????
        $result = $this->validate($data,'Yz.edit',[],[$this,'some']);
        if(true !== $result){
            dump($result);
        }
    }


    ////////////////////////////////       模型验证       ////////////////////////////////

    // 在模型中的验证方式如下
    // ????????????????????
    public function s()
    {
        $data = [
            'name'  => 'thinkphp',
            'email' => 'thinkphp@qq.com',
        ];
        $User = new User;
        $result = $User->validate(
            [
                'name'  => 'require|max:25',
                'email'   => 'email',
            ],
            [
                'name.require' => '名称必须',
                'name.max'     => '名称最多不能超过25个字符',
                'email'        => '邮箱格式错误',
            ]
        )->save($data);
        if(false === $result){
            // 验证失败 输出错误信息
            dump($User->getError());
        }
    }

    // 如果使用验证器类
    public function t()
    {
        $data = [
            'name'  => 'thinkphp',
            'email' => 'thinkphp@qq.com',
        ];
        $User = new User;
        // 调用当前模型对应的User验证器类进行数据验证
        $result = $User->validate(true)->save($data);
        if(false === $result){
            dump($User->getError());
        }

        // 如果需要调用的验证器类和当前的模型名称不一致
        $User = new User;
        // 调用Member验证器类进行数据验证
        $result = $User->validate('Member')->save($data);
        if(false === $result){
            // 验证失败 输出错误信息
            dump($User->getError());
        }

        // 支持场景验证
        $User = new User;
        // 调用Member验证器类进行数据验证
        $result = $User->validate('User.edit')->save($data);
        if(false === $result){
            // 验证失败 输出错误信息
            dump($User->getError());
        }
    }


    ////////////////////////////////       内置规则       ////////////////////////////////

    public function v()
    {

    }


    ////////////////////////////////       静态调用       ////////////////////////////////

    // 如果需要使用内置的规则验证单个数据，可以使用静态调用的方式。
    public function u()
    {
        // 日期格式验证
        Validate::dateFormat('2016-03-09','Y-m-d'); // true
        // 验证是否有效的日期
        Validate::is('2016-06-03','date'); // true
        // 验证是否有效邮箱地址
        Validate::is('thinkphp@qq.com','email'); // true
        // 验证是否在某个范围
        Validate::in('a',['a','b','c']); // true
        // 验证是否大于某个值
        Validate::gt(10,8); // true
        // 正则验证
        Validate::regex(100,'\d+'); // true

        // 更多验证规则可以参考前面的内置规则。
    }


    ////////////////////////////////       表单令牌       ////////////////////////////////

    // 验证规则支持对表单的令牌验证，首先需要在你的表单里面增加下面隐藏域
    // <input type="hidden" name="__token__" value="{$Request.token}" />
    // 或者  {:token()}
    public function w()
    {

    }

    public function x()
    {

    }

    public function y()
    {

    }

    public function z()
    {

    }


}